package com.hsogoo.study.concurrency;

import org.junit.Test;

/**
 * Created by za-huangsaigang on 2018/9/4.
 */
public class ThreadInterruptTest {

    private Object lock = new Object();

    // NEW
    // 线程的new状态表示还未调用start方法，还未真正启动
    @Test
    public void testNewStateInterrupt(){
        Thread t = new Thread();
        System.out.println(t.getState());           //NEW
        t.interrupt();
        System.out.println(t.isInterrupted());      //false
    }

    // TERMINATED
    // 线程的terminated状态表示线程已经运行终止
    @Test
    public void testTerminatedStateInterrupt() throws InterruptedException {
        Thread t = new Thread();
        t.start();
        t.join();
        System.out.println(t.getState());               //TERMINATED
        t.interrupt();
        System.out.println(t.isInterrupted());          //false
    }

    // RUNNABLE
    // 如果线程处于运行状态，那么该线程的状态就是RUNNABLE，
    // 但是不一定所有处于RUNNABLE状态的线程都能获得CPU运行，
    // 在某个时间段，只能由一个线程占用CPU，那么其余的线程虽然状态是RUNNABLE，但是都没有处于运行状态。
    // 处于RUNNABLE状态的线程在遭遇中断操作的时候只会设置该线程的中断标志位，并不会让线程实际中断。
    @Test
    public void testRunnableStateInterrupt() throws InterruptedException {
        Thread thread = new RunningThread();
        thread.start();
        System.out.println(thread.getState());                      //RUNNABLE
        thread.interrupt();
        System.out.println("interrupt thread...");
        Thread.sleep(1000);//等到thread线程被中断之后
        System.out.println(thread.isInterrupted());                 //true
        System.out.println(thread.getState());                      //RUNNABLE
    }

    // 可以通过if判断中断标志位是否被设置来中断我们的程序而不是系统强制的中断。
    @Test
    public void testRunnableStateWithInterruptThreadInterrupt() throws InterruptedException {
        Thread thread = new RunningWithInterruptAbleThread();
        thread.start();
        System.out.println(thread.getState());                  //RUNNABLE
        thread.interrupt();
        System.out.println("interrupt thread...");
        Thread.sleep(1000);//等到thread线程被中断之后
        System.out.println(thread.isInterrupted());             //false
        System.out.println(thread.getState());                  //TERMINATED
    }

    // BLOCKED
    // 当线程处于BLOCKED状态说明该线程由于竞争某个对象的锁失败而被挂在了该对象的阻塞队列上了
    // 那么此时发起中断操作不会对该线程产生任何影响，依然只是设置中断标志位
    @Test
    public void testBlockedStateInterrupt() throws InterruptedException {

        //先启动线程1，并占用锁死循环
        Thread thread1 = new BlockedThread();
        thread1.start();
        Thread.sleep(1000);

        //让线程2在线程1启动后再启动，线程2被阻塞
        Thread thread2 = new BlockedThread();
        thread2.start();
        Thread.sleep(1000);

        //查看2个线程的状态
        System.out.println(thread1.getState());         //RUNNABLE
        System.out.println(thread2.getState());         //BLOCKED

        //线程2中断
        thread2.interrupt();
        System.out.println(thread2.isInterrupted());    // true
        System.out.println(thread2.getState());         // BLOCKED
    }

    /****RUNNABLE和BLOCKED类似，中断后只是更改中断标识，需要程序判断线程的中断状态来做相应的处理****/

    // WAITING & TIMED_WAITING
    // 调用interrupt方法对该线程进行中断，捕获了InterruptedException异常，该线程的中断标志位被清空
    @Test
    public void testWaitingStateInterrupt() throws InterruptedException {
        Thread thread = new WaitingThread();
        thread.start();

        Thread.sleep(500);
        System.out.println(thread.getState());          //WAITING

        thread.interrupt();

        Thread.sleep(1000);
        System.out.println(thread.isInterrupted());     //false
    }

    public class RunningThread extends Thread{

        @Override
        public void run(){
            while(true){
                //do something
            }
        }
    }

    public class RunningWithInterruptAbleThread extends Thread{

        @Override
        public void run(){
            while(true){
                if (Thread.currentThread().isInterrupted()){
                    System.out.println("exit RunningWithInterruptAbleThread");
                    break;
                }
            }
        }
    }

    public class BlockedThread extends Thread{

        @Override
        public void run(){
            doSomething();
        }

        public void doSomething(){
            synchronized (lock){
                while(true){
                    //do something
                }
            }
        }
    }

    public class WaitingThread extends Thread{

        @Override
        public void run(){
            synchronized (this){
                try {
                    wait();
                } catch (InterruptedException e) {
                    System.out.println("i am waiting but facing InterruptException now");
                }
            }
        }
    }
}


